//package com.vision.sales.sv.serv;
//
//import java.io.IOException;
//import java.util.ArrayList;
//import java.util.Collections;
//import java.util.HashMap;
//import java.util.List;
//import java.util.Map;
//
//import javax.servlet.ServletException;
//import javax.servlet.http.HttpServlet;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//
//import net.sf.jasperreports.engine.JRDataSource;
//
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Qualifier;
//import org.springframework.stereotype.Service;
//
//import com.vision.core.cm.exception.RpcException;
//import com.vision.core.sv.db.CustomSessionFactoryBean;
//import com.vision.core.sv.db.mgr.DataManager;
//import com.vision.core.sv.db.mgr.ISimpleCriteria;
//import com.vision.core.sv.db.mgr.SimpleCriteria;
//import com.vision.core.sv.serv.util.ServletUtils;
//import com.vision.sales.cm.data.SalesPermissions;
//import com.vision.sales.cm.data.TransactionStatus;
//import com.vision.sales.cm.db.data.CollectionItem;
//import com.vision.sales.cm.db.data.Product;
//import com.vision.sales.cm.db.data.SalesInvoice;
//import com.vision.sales.sv.db.mgr.CollectionItemManager;
//import com.vision.sales.sv.db.mgr.SalesInvoiceManager;
//import com.vision.sales.sv.report.AbstractDataSource;
//import com.vision.sales.sv.report.ProductGroupSalesRow;
//import com.vision.sales.sv.report.Report;
//import com.vision.sales.sv.report.ReportWriter;
//
///**
// * Servlet for printing Monthly Group Sales report.
// * 
// * This servlet is accessible via the /print/monthly_group_sales path in the URL (see web.xml)
// * 
// * GET parameters:
// * <ul>
// * 	<li>title - the title that will appear in the report
// * 	<li>type - 'M' for monthly, 'A' annual. If parameter is unparseable, this defaults to 'A'.
// * 	<li>months - the months to include, separated by commas (ex: 1,2,3 for Jan to March). Applies when type is M.
// * 	<li>year - the year to include (ex: 2012). Applies when type is either M or A.
// * 	<li>companies - optional comma-separated list of company ids indicating which companies to include. If not specified, all companies will be included.</li>
// * 	<li>customers - optional comma-separated list of customer ids indicating which customers to include. If not specified, all customers will be included.</li>
// * </ul>
// * 
// * Example:
// * <pre>/print/monthly_group_sales?title=Monthly%20Group%20Sales&type=A&year=2012</pre>
// * <pre>/print/monthly_group_sales?title=Monthly%20Group%20Sales&type=M&months=1,2,3</pre>
// * 
// * @author Mark
// */
//@Service("print_monthly_group_sales")
//public class PrintMonthlyGroupSalesServlet extends HttpServlet {
//	
//	private static final long serialVersionUID = 1L;
//	
//	private static final Logger log = LoggerFactory.getLogger(PrintMonthlyGroupSalesServlet.class);
//
//	@Autowired
//	@Qualifier("productGroupManager")
//	private DataManager<ProductGroup> productGroupManager;
//	
//	@Autowired
//	@Qualifier("salesInvoiceManager")
//	private DataManager<SalesInvoice> invoiceManager;
//	
//	@Autowired
//	@Qualifier("collectionItemManager")
//	private DataManager<CollectionItem> collectionItemManager;
//	
//	@Override
//	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
//			throws ServletException, IOException {
//		try {
//			ServletUtils.checkPermissions(SalesPermissions.ViewMonthlyGroupSalesReport);
//		} catch (RpcException e) {
//			resp.sendError(HttpServletResponse.SC_FORBIDDEN, "You are not authorized to perform this operation.");
//			return;
//		} 
//		
//		// Parameters --
//		log.debug("Parsing parameters from URL...");
//		MonthlyGroupReportParams params = new MonthlyGroupReportParams(req);
//		if (params.error != null) {
//			resp.sendError(HttpServletResponse.SC_BAD_REQUEST, params.error);
//			return;
//		}
//		
//		String warnings = params.getWarnings();
//		if (warnings.length() > 0) {
//			log.warn(warnings);
//		}		
//		
//		try {
//			// Build the Report
//			log.debug("Building report...");
//			Report report = new Report();
//			report.setFilename((params.isAnnual() ? "Annual" : "Monthly") + " Group Sales Report " + params.year);
//			report.setTitle(params.title + " " + params.year);
//			report.setSize(params.size);
//			report.setOrientation(params.orientation);
//
//			// Columns and Grouping
//			report.addStringColumn("productgroup", "Product Group", 60, null);
//			
//			if (params.isAnnual()) {
//				for (String m : ProductGroupSalesRow.MONTHS) {
//					report.addDoubleColumn(m, m, 30, null);
//				}
//			} else {
//				for (int m : params.months) {
//					if (m > 0 && m < 13)
//						report.addDoubleColumn(ProductGroupSalesRow.MONTHS[m - 1], ProductGroupSalesRow.MONTHS[m - 1], 30, null);
//				}
//			}
//			
//			report.addDoubleColumn("total", "Total", 40, null);
//			
//			// Data Source
//			log.debug("Creating data source...");
//			report.setDataSource(getDataSource(params));
//			
//			// Print and Write to Stream
//			log.debug("Writing report to stream...");
//			ReportWriter.write(report, resp);
//		} catch (Exception e) {
//			log.error(e.getMessage(), e);
//			resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "The server was unable to process the request.");
//		}
//	}
//
//	@SuppressWarnings("deprecation")
//	private JRDataSource getDataSource(MonthlyGroupReportParams params) {
//		Map<Long, ProductGroupSalesRow> map = new HashMap<Long, ProductGroupSalesRow>();
//		
//		// -----
//		ProductGroupSalesRow invoicesTotal = new ProductGroupSalesRow("Total");
//		
//		List<ProductGroup> productGroups = getProductGroups();
//		for (ProductGroup productGroup : productGroups) {
//			ProductGroupSalesRow row = map.get(productGroup.getId());
//			if (row == null) {
//				row = new ProductGroupSalesRow(productGroup, new HashMap<String, Double>());
//				map.put(productGroup.getId(), row);
//			}
//		}		
//		
//		List<SalesInvoice> invoices = getInvoices(params);
//		for (SalesInvoice invoice : invoices) {
//			Product product = invoice.getProduct();
//			Long productGrpId = product.getGroup().getId();
//			ProductGroupSalesRow row = map.get(productGrpId);
//			
//			String mo = ProductGroupSalesRow.MONTHS[invoice.getDate().getMonth()];
//			
//			fillProductGroupSalesRow(row, mo, invoice.getGrossSales());
//			fillProductGroupSalesRow(invoicesTotal, mo, invoice.getGrossSales());
//		}
//		
//		List<ProductGroupSalesRow> list = new ArrayList<ProductGroupSalesRow>(map.values());
//		Collections.sort(list);
//		
//		list.add(invoicesTotal);
//		
//		// -----
//		List<CollectionItem> items = getCollectionItems(params);
//		
//		ProductGroupSalesRow gross = new ProductGroupSalesRow("Gross Sales");
//		ProductGroupSalesRow overruns = new ProductGroupSalesRow("Overruns");
//		ProductGroupSalesRow overpayments = new ProductGroupSalesRow("Overpayments");
//		ProductGroupSalesRow discounts = new ProductGroupSalesRow("Discounts");
//		ProductGroupSalesRow rejects = new ProductGroupSalesRow("Rejects");
//		ProductGroupSalesRow returns = new ProductGroupSalesRow("Returns");
//		ProductGroupSalesRow badDebts = new ProductGroupSalesRow("Bad Debts");
//		ProductGroupSalesRow subtotal = new ProductGroupSalesRow("Subtotal");
//		ProductGroupSalesRow tax = new ProductGroupSalesRow("Tax");
//		ProductGroupSalesRow netAmount= new ProductGroupSalesRow("Net Amount");
//		
//		for (CollectionItem item : items) {
//			String mo = ProductGroupSalesRow.MONTHS[item.getDate().getMonth()];
//			
//			fillProductGroupSalesRow(gross, mo, item.getAmount());
//			fillProductGroupSalesRow(overruns, mo, item.getOverruns());
//			fillProductGroupSalesRow(overpayments, mo, item.getOverpayments());
//			fillProductGroupSalesRow(discounts, mo, item.getDiscounts());
//			fillProductGroupSalesRow(rejects, mo, item.getRejects());
//			fillProductGroupSalesRow(returns, mo, item.getReturns());
//			fillProductGroupSalesRow(subtotal, mo, item.getSubtotal());
//			fillProductGroupSalesRow(tax, mo, item.getTax());
//			fillProductGroupSalesRow(netAmount, mo, item.getNetAmount());
//		}
//		
//		// -----
//		
//		ProductGroupSalesRow dummy = new ProductGroupSalesRow("") {
////			public void computeTotal() {};
//		};
//		
//		list.add(dummy);
//		list.add(dummy);
//		list.add(gross);
//		list.add(overruns);
//		list.add(overpayments);
//		list.add(discounts);
//		list.add(rejects);
//		list.add(returns);
//		list.add(badDebts);
//		list.add(subtotal);
//		list.add(tax);
//		list.add(netAmount);
//		
//		for (ProductGroupSalesRow row : list)
//			row.computeTotal();
//		
//		JRDataSource ds = new AbstractDataSource<ProductGroupSalesRow>(list) {
//			@Override
//			public Object getValue(ProductGroupSalesRow object, String fieldName) {
//				if ("productgroup".equals(fieldName)) {
//					return object.getProductGroupName();
//				}
//				
//				Object value = object.get(fieldName);
//				return value;
//			}
//		};
//		return ds;
//	}
//	
//	void fillProductGroupSalesRow(ProductGroupSalesRow row, String month, Double amount) {
//		if (amount == null) amount = 0d;
//		
//		Double value = row.getSalesMap().get(month);
//		if (value == null)
//			row.getSalesMap().put(month, amount);
//		else
//			row.getSalesMap().put(month, value + amount);
//	}
//	
//	@SuppressWarnings("unchecked")
//	protected List<ProductGroup> getProductGroups() {
//		// XXX @Autowired doesn't seem to work, thus this patch
//		productGroupManager = new ProductGroupManager();
//		productGroupManager.setSessionFactory(CustomSessionFactoryBean.getFactory());
//		
//		ISimpleCriteria crit = SimpleCriteria.forClass(ProductGroup.class);		
//		crit.asc("code");
//		
//		log.debug("Retrieving product groups...");
//		List<ProductGroup> productGroups = productGroupManager.getTemplate().findByCriteria(crit.getDetached());
//		return productGroups;
//	}
//	
//	@SuppressWarnings("unchecked")
//	protected List<SalesInvoice> getInvoices(MonthlyGroupReportParams params) {
//		// XXX @Autowired doesn't seem to work, thus this patch
//		invoiceManager = new SalesInvoiceManager();
//		invoiceManager.setSessionFactory(CustomSessionFactoryBean.getFactory());
//		
//		ISimpleCriteria crit = SimpleCriteria.forClass(SalesInvoice.class);
//		crit.eq("status", TransactionStatus.POSTED);
//		
//		crit.add(DateExtract.year("date", params.year));
//		
//		if (!params.isAnnual())
//			crit.add(DateExtract.in("MONTH", "date", params.months));
//		
//		if (params.companyIds != null && !params.companyIds.isEmpty())
//			crit.in("company.id", params.companyIds);
//		
//		if (params.customerIds != null && !params.customerIds.isEmpty())
//			crit.in("customer.id", params.customerIds);
//		
//		crit.asc("date");
//		
//		log.debug("Retrieving sales invoices...");
//		List<SalesInvoice> invoices = invoiceManager.getTemplate().findByCriteria(crit.getDetached());
//		return invoices;
//	}
//	
//	@SuppressWarnings("unchecked")
//	protected List<CollectionItem> getCollectionItems(MonthlyGroupReportParams params) {
//		// XXX @Autowired doesn't seem to work, thus this patch
//		collectionItemManager = new CollectionItemManager();
//		collectionItemManager.setSessionFactory(CustomSessionFactoryBean.getFactory());
//		
//		ISimpleCriteria crit = SimpleCriteria.forClass(CollectionItem.class);
//		// TODO Get collections first then get CollectionItem
////		crit.eq("collection.status", TransactionStatus.POSTED);
//		
//		crit.add(DateExtract.year("date", params.year));
//		
//		if (!params.isAnnual())
//			crit.add(DateExtract.in("MONTH", "date", params.months));
//		
//		if (params.companyIds != null && !params.companyIds.isEmpty())
//			crit.in("company.id", params.companyIds);
//		
//		if (params.customerIds != null && !params.customerIds.isEmpty())
//			crit.in("customer.id", params.customerIds);
//		
//		crit.asc("date");
//		
//		log.debug("Retrieving collection items...");
//		List<CollectionItem> items = collectionItemManager.getTemplate().findByCriteria(crit.getDetached());
//		return items;
//	}
//
//	private class MonthlyGroupReportParams extends PeriodSalesReportParams {
//		
//		public MonthlyGroupReportParams(HttpServletRequest req) {
//			super(req);
//			setDefaultTitle("Product Sales Report");
//		}
//	}
//}
